package controller;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class ControlServlet extends HttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private static final String mappingConfigFilePath = "WEB-INF/mapping-config.xml";
	private static Map<String, HttpServlet> actionOrViewMap = new HashMap<String, HttpServlet>();

	/**
	 * Destruction of the servlet. <br>
	 */
	public void destroy() {
		super.destroy(); // Just puts "destroy" string in log
		// Put your code here
	}

	protected void service(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		
		System.out.println("Request is being processed by front controller...");
		
		String path = request.getServletPath();
		int n = path.lastIndexOf("/");
		path = path.substring(n);
		System.out.println("The last part of url is: " + path);
		
		HttpServlet processServlet = actionOrViewMap.get(path);
		if(processServlet!=null) {
			processServlet.service(request, response);
		}
		else {	// redirect to 404 error page
			request.getRequestDispatcher("/404.jsp").forward(request, response);
		}
	}

	/**
	 * Initialization of the servlet. <br>
	 * 
	 * @throws ServletException
	 *             if an error occurs
	 */
	public void init() throws ServletException {
		String realPath=this.getServletConfig().getServletContext().getRealPath("/");
		final String xmlFile=realPath+mappingConfigFilePath;
		
		// Dom parses WEB-INF/mapping-config.xml
		DocumentBuilderFactory factory = null;
		DocumentBuilder builder = null;
		factory = DocumentBuilderFactory.newInstance();
		if (factory != null) {
			try {
				builder = factory.newDocumentBuilder();
			} catch (ParserConfigurationException e) {
				e.printStackTrace();
			}
		}
		Document doc = null;
		try {
			doc = builder.parse(new File(xmlFile));
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		System.out.println("the path of mapping-config is: " + xmlFile);
		System.out.println("mapping-config file exists? " + new File(xmlFile).exists());
		NodeList nodeList = doc.getElementsByTagName("mapping");
		int len = nodeList.getLength();
		for (int i = 0; i < len; i++) {
			Element elementAction = (Element) nodeList.item(i);
			Node pathNode = elementAction.getElementsByTagName("path").item(0);
			Node classNode = elementAction.getElementsByTagName("url").item(0);
			String path = pathNode.getFirstChild().getNodeValue();
			String name = classNode.getFirstChild().getNodeValue();
			HttpServlet servlet = null;
			try {
				servlet = (HttpServlet) Class.forName(name).newInstance();
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
			
			actionOrViewMap.put(path, servlet);
		}

	}

}